#include<stdio.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include<ctype.h>
#include<iostream>
#include<list>

using namespace std;

#define TAM_MAX_PALAVRA 100
#define TAM_MAX_PRIMO 2000
#define BILLION 1E9

/* Retorna a soma do calor ASCII de cada letra de uma palavra */
int soma_letras(char string[]){
	int i, tam, soma = 0;

	tam = strlen(string);

	for(i = 0; i < tam; i++)
		soma = soma + string[i];

	return soma;
}

/* Retorna 1 se o numero n for primo, se não retorna 0 */
int primo(int n){
	int i, j, raiz;
	int vetorPrimos[TAM_MAX_PRIMO];

	raiz = sqrt(n);

	for(i = 2; i <= n; i++)
		vetorPrimos[i] = i;

	for(i = 2; i <= raiz; i++)
		if (vetorPrimos[i] == i) 
			for(j = i*i; j <= n; j=j+i)
				vetorPrimos[j] = 0;

	return ((vetorPrimos[n] == 0) ? 0 : 1);
}

/* Retorna 1 se a string é um palindromo, se não retorna 0 */
int palindromo(char string[]){
	int i, tam, tam_aux, flag = 1;
	char string_aux[TAM_MAX_PALAVRA];

	strcpy(string_aux, string);

	tam = strlen(string_aux);
	tam_aux = tam/2;

	for(i = 0; i < tam; i++)
		if(isupper(string_aux[i]))
			string_aux[i] = tolower(string_aux[i]);

	for(i = 0; i < tam_aux; i++){
		if(string_aux[i] != string_aux[tam-i-1])
			flag = 0;
	}

	return flag;
}

int main(){
	char c, palavra[TAM_MAX_PALAVRA];
	int i = 0, flag = 0, num_palindromos = 0, num_primos = 0;
	FILE *fp, *fp_out;
	struct timespec time1, time2;
	double diff, diff2;

	list<string> palavras;
	list<string>::iterator it = palavras.begin();
	string aux;

	fp = fopen("wikipedia.txt", "r+");
	fp_out = fopen("wikipedia_out.txt", "w+");

	/* Pre-processamento do arquivo, apenas queremos letras e numeros, o resto vira _ */
	c = fgetc(fp);
	while(c != EOF){
		/* Se for diferente de numeros ou letras, colocamos _ */
		if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z'))
			fputc('_', fp_out);
		else
			fputc(c, fp_out);
		c = fgetc(fp);
	}

	/* Agora voltamos para o inicio do arquivo e separamos as palavras */
	fseek(fp_out, 0, SEEK_SET);
	c = fgetc(fp_out);
	while(c != EOF){
		if(c != '_') /* nosso delimitador é _ */
			palavra[i++] = c;
		else if (i != 0)
			flag = 1;

		if(flag == 1){
			palavra[i] = '\0';
			if(i > 1)
				palavras.insert(it, palavra);
			i = 0;
			flag = 0;
		}
		c = fgetc(fp_out);
	}

	clock_gettime(CLOCK_REALTIME, &time1);
	/* Percorre a lista procurando palindromos */
	for(it = palavras.begin(); it != palavras.end(); it++){
		aux = *it;

		/* Passamos a palavra de string (c++) para um array de chars (c) */
		for(i = 0; i < aux.size(); i++)
			palavra[i] = aux[i];
		palavra[i] = '\0';

		/* Vemos se é palindromo, se for vemos se o mapeamento ASCII é primo */
		if(palindromo(palavra)){
			num_palindromos++;
			if(primo(soma_letras(palavra)))
				num_primos++;
		}
	}
	clock_gettime(CLOCK_REALTIME, &time2);

	diff = (time2.tv_sec-time1.tv_sec)+(time2.tv_nsec-time1.tv_nsec)/BILLION;

	printf("Numero de palindromos no texto: %d\n", num_palindromos);
	printf("Numero de primos nos palindromos: %d\n", num_primos);
	printf("Tempo para verificação de palindromos: %lf segundos\n",diff);

	fclose(fp);
	fclose(fp_out);

	return 0;
}
